using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.IO;


//comment
namespace PankowGame13
{
    public enum GameState
    {
        TitleScreen,
        MainMenu,
        GameRunning,
        ChangeLevel,
        Merchant,
        GameOver
    }
    public enum MenuOptions
    {
        Adventurer,
        Hunter,
        Mage,
        Rogue,
        Warrior
    }
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GameState currentGameState = GameState.TitleScreen;
        string levelPath = "Content\\Levels\\";
        string itemPath = "Content\\Items\\";
        string highScorePath = "Content\\HighScores\\highscore.txt";
        List<string> highScores;
        int dungeonLevel = 1;
        int timeMark;
        char[,] levelDesign = new char[20, 15];
        Tile[,] levelInTiles = new Tile[20, 15];
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Texture2D path, wall, barrier;
        Texture2D background, mainMenu, titleScreen, merchant;

        Item merchantItemOffer;
        int merchantItemPrice;
        bool merchantChoseItem;

        MenuOptions currentMenuOption = MenuOptions.Adventurer;

        FloatingTextManager ftm;

        Texture2D wasdKeys, qKey, spaceBar;

        Texture2D level, gameOverBad, gameOverGood, levelChange;
        Player thePlayer;

        SoundEffect combat, treasure, loot, levelSound;

        List<string> itemImport;
        List<string> helms;
        List<string> armors;
        List<string> legs;
        List<string> boots;
        List<string> weapons;
        List<string> shields;
        List<string> rings;
        List<string> necklaces;

        Texture2D potion;

        List<Enemy> enemyList;

        List<string> levelList;
        int currentLevel = 0;

        int highScore = 0;
        string playerName = "AAA";
        string tempPlayerName = "";

        KeyboardState kbs;
        KeyboardState prevKbs;
        SpriteFont sf;

        public void LoadLevels()
        {
            levelList = new List<string>();
            var fileNames = from fullFileName in Directory.EnumerateFiles(levelPath)
                            select Path.GetFileName(fullFileName);
            foreach (var f in fileNames)
            {
                levelList.Add(f.ToString());
            }
            levelList.Shuffle();
        }

        public void ConstructLevelArray()
        {
            StreamReader sr = new StreamReader(levelPath + levelList[currentLevel]);
           // StreamReader sr = new StreamReader(levelPath + "BrendanMap9.map");
            currentLevel++;
            int x = 0;
            int y = 0;
            int locationX = 0;
            int locationY = 0;
            int size = 50;

            while (!sr.EndOfStream)
            {
                char temp = (char)sr.Read();
                levelDesign[y, x] = temp;
                //B=Barrier P=Path W=Wall T=Treasure L=Loot U=UpLadder D=DownLadder
                //A=UpArrow V=DownArrow
                if (temp == 'B')
                {
                    levelInTiles[y, x] = new BarrierTile("Hole Floor", new Vector2(locationX, locationY), size, Content);
                }
                if (temp == 'P')
                {
                    levelInTiles[y, x] = new PathTile("Basic Floor light 2", new Vector2(locationX, locationY), size, Content);
                }
                if (temp == 'W')
                {
                    levelInTiles[y, x] = new WallTile("Crack Floor", new Vector2(locationX, locationY), size, Content, false);
                }
                if (temp == 'T')
                {
                    levelInTiles[y, x] = new TreasureTile("Loot Chest", new Vector2(locationX, locationY), size, "T", dungeonLevel, false, Content, thePlayer.playerTreasureFind,
                        helms, armors, legs, boots, weapons, shields, rings, necklaces);
                }
                if (temp == 'L')
                {
                    levelInTiles[y, x] = new TreasureTile("Loot Chest", new Vector2(locationX, locationY), size, "L",dungeonLevel, false, Content, thePlayer.playerTreasureFind,
                        helms, armors, legs, boots, weapons, shields, rings, necklaces);
                }
                if (temp == 'U')
                {
                    levelInTiles[y, x] = new LadderTile("Ladder Floor Closed", new Vector2(locationX, locationY), size, false, Content);
                }
                if (temp == 'D')
                {
                    levelInTiles[y, x] = new LadderTile("Ladder Floor Closed", new Vector2(locationX, locationY), size, true, Content);
                }
                if (temp == 'M')
                {
                    levelInTiles[y, x] = new MonsterTile("Basic Floor light 2", new Vector2(locationX, locationY), size, Content);
                }
                if (temp == 't')
                {
                    levelInTiles[y, x] = new TrapTile("Basic Floor light 2", new Vector2(locationX, locationY), size, Content);
                }
                if (temp == 'l')
                {
                    levelInTiles[y, x] = new TreasureTile("Basic Floor light 2", new Vector2(locationX, locationY), size, "T", dungeonLevel, true, Content, thePlayer.playerTreasureFind,
                        helms, armors, legs, boots, weapons, shields, rings, necklaces);
                }
                if (temp == 'H')
                {
                    levelInTiles[y, x] = new WallTile("Crack Floor", new Vector2(locationX, locationY), size, Content, true);
                }

                locationX += size;
                x++;

                if (locationX == 20 * size)
                {
                    locationX = 0;
                    locationY += size;
                }
                if (x > 14)
                {
                    x = 0;
                    y++;
                }
            }
            sr.Close();

            foreach(Tile t in levelInTiles)
            {
                if (t.GetType().ToString() == "PankowGame13.MonsterTile")
                {
                    //could be randomized with more enemy types
                    enemyList.Add(new Enemy(EnemyType.Kobold, thePlayer.dungeonLevel, "monstar", Content, t.tileLocation + new Vector2(5,10), new Vector2(30, 35)));
                }
            }

        }

        public void ParseItems(List<string> rawItems)
        {
            foreach (string s in rawItems)
            {
                switch (s[0])
                {
                    case '0':
                        helms.Add(s);
                        break;
                    case '1':
                        armors.Add(s);
                        break;
                    case'2':
                        legs.Add(s);
                        break;
                    case '3':
                        boots.Add(s);
                        break;
                    case '4':
                        weapons.Add(s);
                        break;
                    case '5':
                        shields.Add(s);
                        break;
                    case '6':
                        rings.Add(s);
                        break;
                    case '7':
                        necklaces.Add(s);
                        break;

                }
                
            }

        }

        public List<string> ParseHighScores()
        {
            //load high scores
            StreamReader sr;
            List<string> output = new List<string>();
            string[] tempHighScore = new string[3];
            string[] nameAndLevel = new string[]{"0-0-0","0-0-0","0-0-0","0-0-0","0-0-0","0-0-0"};
            int[] score = new int[6];

            int recordNum = 0;
            sr = new StreamReader(highScorePath);

            while (!sr.EndOfStream)
            {
                tempHighScore = sr.ReadLine().Split('-');
                nameAndLevel[recordNum] = tempHighScore[0] + "-" + tempHighScore[2];
                score[recordNum] = Convert.ToInt32(tempHighScore[1]);
                recordNum++;
            }
            Array.Sort(score, nameAndLevel);
            Array.Reverse(score);
            Array.Reverse(nameAndLevel);
            sr.Close();

            StreamWriter sw = new StreamWriter(highScorePath);
            for (int i = 0; i < 5; i++)
            {
                string[] nameLevelSplit = nameAndLevel[i].Split('-');
                output.Add(nameLevelSplit[0] + "    " + score[i] + "    " + nameLevelSplit[1]);
                sw.WriteLine(nameLevelSplit[0] + "-" + score[i] + "-" + nameLevelSplit[1]);
            }
            sw.Close();
            return output;
        }

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            combat = Content.Load<SoundEffect>(@"punch");
            loot = Content.Load<SoundEffect>(@"loot");
            treasure = Content.Load<SoundEffect>(@"coin");
            levelSound = Content.Load<SoundEffect>(@"openLadder");

            highScores = new List<string>();
            itemImport = new List<string>();
            helms = new List<string>();
            armors = new List<string>();
            legs = new List<string>();
            boots = new List<string>();
            weapons = new List<string>();
            shields = new List<string>();
            rings = new List<string>();
            necklaces = new List<string>();

            merchantItemOffer = new Item(Content);
            merchantItemPrice = 0;
            merchantChoseItem = false;

            StreamReader sr = new StreamReader(itemPath + "items.txt");
            while (!sr.EndOfStream)
            {
                itemImport.Add(sr.ReadLine());
            }
            sr.Close();
            ParseItems(itemImport);

            //thePlayer = new Player(new Vector2(60, 60), new Vector2(30, 35), Content, PlayerClass.Warrior);
            enemyList = new List<Enemy>();

            potion = Content.Load<Texture2D>(@"potion");

            IsMouseVisible = true;
            graphics.IsFullScreen = false;
            graphics.PreferredBackBufferWidth = 1250;
            graphics.PreferredBackBufferHeight = 800;
            graphics.ApplyChanges();
            
            //default implementation for preloading
            thePlayer = new Player(Vector2.Zero, new Vector2(20, 20), Content, PlayerClass.Adventurer);
            // TODO: Add your initialization logic here

            LoadLevels();
            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            sf = Content.Load<SpriteFont>(@"SpriteFont1");
            ftm = new FloatingTextManager(sf, Color.White);
            level = Content.Load<Texture2D>(@"level Map");

            background = Content.Load<Texture2D>(@"Stone Background");
            mainMenu = Content.Load<Texture2D>(@"Main Menu");
            titleScreen = Content.Load<Texture2D>(@"Title");
            gameOverBad = Content.Load<Texture2D>(@"GameoverBad");
            gameOverGood = Content.Load<Texture2D>(@"Victorious");
            levelChange = Content.Load<Texture2D>(@"Level Chage");
            merchant = Content.Load<Texture2D>(@"Merchant Screen");

            path = Content.Load<Texture2D>(@"Basic Floor");
            wall = Content.Load<Texture2D>(@"Water Floor");
            barrier = Content.Load<Texture2D>(@"Lava Floor");

            wasdKeys = Content.Load<Texture2D>(@"wasd");
            qKey = Content.Load<Texture2D>(@"qkey");
            spaceBar = Content.Load<Texture2D>(@"spacebar");
            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            kbs = Keyboard.GetState();

            switch (currentGameState)
            {
                case GameState.TitleScreen:
                    if (kbs.IsKeyDown(Keys.Enter) || kbs.IsKeyDown(Keys.Space))
                    {
                        currentGameState = GameState.MainMenu;
                        //read from high score file, and parse
                        highScores = ParseHighScores();

                    }
                    break;
                case GameState.MainMenu:
                    if (kbs.IsKeyDown(Keys.S) && prevKbs.IsKeyUp(Keys.S))
                    {
                        switch (currentMenuOption)
                        {
                            case MenuOptions.Adventurer:
                                currentMenuOption = MenuOptions.Hunter;
                                break;
                            case MenuOptions.Hunter:
                                currentMenuOption = MenuOptions.Mage;
                                break;
                            case MenuOptions.Mage:
                                currentMenuOption = MenuOptions.Rogue;
                                break;
                            case MenuOptions.Rogue:
                                currentMenuOption = MenuOptions.Warrior;
                                break;
                            case MenuOptions.Warrior:
                                currentMenuOption = MenuOptions.Adventurer;
                                break;
                        }
                    }
                    if (kbs.IsKeyDown(Keys.W) && prevKbs.IsKeyUp(Keys.W))
                    {
                        switch (currentMenuOption)
                        {
                            case MenuOptions.Adventurer:
                                currentMenuOption = MenuOptions.Warrior;
                                break;
                            case MenuOptions.Hunter:
                                currentMenuOption = MenuOptions.Adventurer;
                                break;
                            case MenuOptions.Mage:
                                currentMenuOption = MenuOptions.Hunter;
                                break;
                            case MenuOptions.Rogue:
                                currentMenuOption = MenuOptions.Mage;
                                break;
                            case MenuOptions.Warrior:
                                currentMenuOption = MenuOptions.Rogue;
                                break;
                        }
                    }
                    if (kbs.IsKeyDown(Keys.Enter) && prevKbs.IsKeyUp(Keys.Enter))
                    {
                        switch (currentMenuOption)
                        {
                            case MenuOptions.Adventurer:
                                //thePlayer.theClass = PlayerClass.Adventurer;
                                thePlayer = new Player(new Vector2(60, 60), new Vector2(30, 35), Content, PlayerClass.Adventurer);
                                break;
                            case MenuOptions.Hunter:
                                //thePlayer.theClass = PlayerClass.Hunter;
                                thePlayer = new Player(new Vector2(60, 60), new Vector2(30, 35), Content, PlayerClass.Hunter);
                                break;
                            case MenuOptions.Mage:
                                //thePlayer.theClass = PlayerClass.Mage;
                                thePlayer = new Player(new Vector2(60, 60), new Vector2(30, 35), Content, PlayerClass.Mage);
                                break;
                            case MenuOptions.Rogue:
                                //thePlayer.theClass = PlayerClass.Rogue;
                                thePlayer = new Player(new Vector2(60, 60), new Vector2(30, 35), Content, PlayerClass.Rogue);
                                break;
                            case MenuOptions.Warrior:
                                //thePlayer.theClass = PlayerClass.Warrior;
                                thePlayer = new Player(new Vector2(60, 60), new Vector2(30, 35), Content, PlayerClass.Warrior);
                                break;
                        }
                        ConstructLevelArray();

                        foreach (Tile t in levelInTiles)
                        {
                            if (t.GetType().ToString() == "PankowGame13.LadderTile")
                            {
                                LadderTile tempTile = (LadderTile)t;
                                if (!tempTile.isDown)
                                {
                                    thePlayer.playerPosition = new Rectangle(tempTile.tileRect.X, tempTile.tileRect.Y, thePlayer.playerPosition.Width, thePlayer.playerPosition.Height);
                                }
                            }
                        }

                        currentGameState = GameState.GameRunning;
                    }
                    break;
                case GameState.ChangeLevel:
                    enemyList.Clear();
                    dungeonLevel++;
                    ConstructLevelArray();
                    foreach (Tile t in levelInTiles)
                    {
                        if (t.GetType().ToString() == "PankowGame13.LadderTile")
                        {
                            LadderTile tempTile = (LadderTile)t;
                            if (!tempTile.isDown)
                            {
                                thePlayer.playerPosition = new Rectangle(tempTile.tileRect.X, tempTile.tileRect.Y, thePlayer.playerPosition.Width, thePlayer.playerPosition.Height);
                            }
                        }
                    }

                    int targetTime = timeMark + 23;
                    while (timeMark <= targetTime)
                    {
                        timeMark++;
                        System.Threading.Thread.Sleep(100);
                    }

                    currentGameState = GameState.Merchant;
                    break;
                case GameState.Merchant:
                    Random rand = new Random();

                    if (!merchantChoseItem)
                    {
                        merchantItemOffer = new Item(dungeonLevel, Content, 0, true,
                            helms, armors, legs, boots, weapons, shields, rings, necklaces);
                        merchantItemPrice = (rand.Next(1 + dungeonLevel, 6 + dungeonLevel) + (dungeonLevel + (dungeonLevel / 2) ));

                        if (dungeonLevel >= 10 && dungeonLevel < 20)
                        {
                            merchantItemPrice *= (2 + dungeonLevel);
                        }
                        if (dungeonLevel >= 20 && dungeonLevel < 30)
                        {
                            merchantItemPrice *= (3 + dungeonLevel);
                        }
                        if (dungeonLevel >= 30 && dungeonLevel < 40)
                        {
                            merchantItemPrice *= (6 + dungeonLevel);
                        }
                        if (dungeonLevel >= 40 && dungeonLevel < 50)
                        {
                            merchantItemPrice *= (12 + dungeonLevel);
                        }
                        if (dungeonLevel >= 50)
                        {
                            merchantItemPrice *= (24 + dungeonLevel);
                        }

                        if (merchantItemOffer.itemType == ItemTypes.Potion)
                        {
                            merchantItemPrice = 30;
                        }
                        merchantChoseItem = true;
                    }

                    if (kbs.IsKeyDown(Keys.Y) && prevKbs.IsKeyUp(Keys.Y))
                    {
                        if (thePlayer.playerTreasureAmount >= merchantItemPrice)
                        {
                            thePlayer.playerTreasureAmount -= merchantItemPrice;
                            
                            thePlayer.playerMaxHealth += merchantItemOffer.itemBuffs[0];
                            thePlayer.playerHealth += merchantItemOffer.itemBuffs[0];
                            thePlayer.playerSpeed += merchantItemOffer.itemBuffs[1];
                            thePlayer.playerStrength += merchantItemOffer.itemBuffs[2];
                            thePlayer.playerIntelligence += merchantItemOffer.itemBuffs[3];
                            thePlayer.playerDefense += merchantItemOffer.itemBuffs[4];
                            thePlayer.attack += merchantItemOffer.itemBuffs[5];
                            thePlayer.weaponStrength += merchantItemOffer.itemBuffs[6];
                            thePlayer.playerTreasureFind += merchantItemOffer.itemBuffs[7];
                            
                            switch (merchantItemOffer.itemType)
                            {
                                case ItemTypes.Helm:
                                    thePlayer.playerMaxHealth -= thePlayer.playerItems[0].itemBuffs[0];
                                    thePlayer.playerHealth -= thePlayer.playerItems[0].itemBuffs[0];
                                    thePlayer.playerSpeed -= thePlayer.playerItems[0].itemBuffs[1];
                                    thePlayer.playerStrength -= thePlayer.playerItems[0].itemBuffs[2];
                                    thePlayer.playerIntelligence -= thePlayer.playerItems[0].itemBuffs[3];
                                    thePlayer.playerDefense -= thePlayer.playerItems[0].itemBuffs[4];
                                    thePlayer.attack -= thePlayer.playerItems[0].itemBuffs[5];
                                    thePlayer.weaponStrength -= thePlayer.playerItems[0].itemBuffs[6];
                                    thePlayer.playerTreasureFind -= thePlayer.playerItems[0].itemBuffs[7];

                                    thePlayer.playerItems[0] = merchantItemOffer;
                                    break;
                                case ItemTypes.Chest:
                                    thePlayer.playerMaxHealth -= thePlayer.playerItems[1].itemBuffs[0];
                                    thePlayer.playerHealth -= thePlayer.playerItems[1].itemBuffs[0];
                                    thePlayer.playerSpeed -= thePlayer.playerItems[1].itemBuffs[1];
                                    thePlayer.playerStrength -= thePlayer.playerItems[1].itemBuffs[2];
                                    thePlayer.playerIntelligence -= thePlayer.playerItems[1].itemBuffs[3];
                                    thePlayer.playerDefense -= thePlayer.playerItems[1].itemBuffs[4];
                                    thePlayer.attack -= thePlayer.playerItems[1].itemBuffs[5];
                                    thePlayer.weaponStrength -= thePlayer.playerItems[1].itemBuffs[6];
                                    thePlayer.playerTreasureFind -= thePlayer.playerItems[1].itemBuffs[7];

                                    thePlayer.playerItems[1] = merchantItemOffer;
                                    break;
                                case ItemTypes.Legs:
                                    thePlayer.playerMaxHealth -= thePlayer.playerItems[2].itemBuffs[0];
                                    thePlayer.playerHealth -= thePlayer.playerItems[2].itemBuffs[0];
                                    thePlayer.playerSpeed -= thePlayer.playerItems[2].itemBuffs[1];
                                    thePlayer.playerStrength -= thePlayer.playerItems[2].itemBuffs[2];
                                    thePlayer.playerIntelligence -= thePlayer.playerItems[2].itemBuffs[3];
                                    thePlayer.playerDefense -= thePlayer.playerItems[2].itemBuffs[4];
                                    thePlayer.attack -= thePlayer.playerItems[2].itemBuffs[5];
                                    thePlayer.weaponStrength -= thePlayer.playerItems[2].itemBuffs[6];
                                    thePlayer.playerTreasureFind -= thePlayer.playerItems[2].itemBuffs[7];

                                    thePlayer.playerItems[2] = merchantItemOffer;
                                    break;
                                case ItemTypes.Boots:
                                    thePlayer.playerMaxHealth -= thePlayer.playerItems[3].itemBuffs[0];
                                    thePlayer.playerHealth -= thePlayer.playerItems[3].itemBuffs[0];
                                    thePlayer.playerSpeed -= thePlayer.playerItems[3].itemBuffs[1];
                                    thePlayer.playerStrength -= thePlayer.playerItems[3].itemBuffs[2];
                                    thePlayer.playerIntelligence -= thePlayer.playerItems[3].itemBuffs[3];
                                    thePlayer.playerDefense -= thePlayer.playerItems[3].itemBuffs[4];
                                    thePlayer.attack -= thePlayer.playerItems[3].itemBuffs[5];
                                    thePlayer.weaponStrength -= thePlayer.playerItems[3].itemBuffs[6];
                                    thePlayer.playerTreasureFind -= thePlayer.playerItems[3].itemBuffs[7];

                                    thePlayer.playerItems[3] = merchantItemOffer;
                                    break;
                                case ItemTypes.Weapon:
                                    thePlayer.playerMaxHealth -= thePlayer.playerItems[4].itemBuffs[0];
                                    thePlayer.playerHealth -= thePlayer.playerItems[4].itemBuffs[0];
                                    thePlayer.playerSpeed -= thePlayer.playerItems[4].itemBuffs[1];
                                    thePlayer.playerStrength -= thePlayer.playerItems[4].itemBuffs[2];
                                    thePlayer.playerIntelligence -= thePlayer.playerItems[4].itemBuffs[3];
                                    thePlayer.playerDefense -= thePlayer.playerItems[4].itemBuffs[4];
                                    thePlayer.attack -= thePlayer.playerItems[4].itemBuffs[5];
                                    thePlayer.weaponStrength -= thePlayer.playerItems[4].itemBuffs[6];
                                    thePlayer.playerTreasureFind -= thePlayer.playerItems[4].itemBuffs[7];

                                    thePlayer.playerItems[4] = merchantItemOffer;
                                    break;
                                case ItemTypes.Shield:
                                    thePlayer.playerMaxHealth -= thePlayer.playerItems[5].itemBuffs[0];
                                    thePlayer.playerHealth -= thePlayer.playerItems[5].itemBuffs[0];
                                    thePlayer.playerSpeed -= thePlayer.playerItems[5].itemBuffs[1];
                                    thePlayer.playerStrength -= thePlayer.playerItems[5].itemBuffs[2];
                                    thePlayer.playerIntelligence -= thePlayer.playerItems[5].itemBuffs[3];
                                    thePlayer.playerDefense -= thePlayer.playerItems[5].itemBuffs[4];
                                    thePlayer.attack -= thePlayer.playerItems[5].itemBuffs[5];
                                    thePlayer.weaponStrength -= thePlayer.playerItems[5].itemBuffs[6];
                                    thePlayer.playerTreasureFind -= thePlayer.playerItems[5].itemBuffs[7];

                                    thePlayer.playerItems[5] = merchantItemOffer;
                                    break;
                                case ItemTypes.Ring:
                                    thePlayer.playerMaxHealth -= thePlayer.playerItems[6].itemBuffs[0];
                                    thePlayer.playerHealth -= thePlayer.playerItems[6].itemBuffs[0];
                                    thePlayer.playerSpeed -= thePlayer.playerItems[6].itemBuffs[1];
                                    thePlayer.playerStrength -= thePlayer.playerItems[6].itemBuffs[2];
                                    thePlayer.playerIntelligence -= thePlayer.playerItems[6].itemBuffs[3];
                                    thePlayer.playerDefense -= thePlayer.playerItems[6].itemBuffs[4];
                                    thePlayer.attack -= thePlayer.playerItems[6].itemBuffs[5];
                                    thePlayer.weaponStrength -= thePlayer.playerItems[6].itemBuffs[6];
                                    thePlayer.playerTreasureFind -= thePlayer.playerItems[6].itemBuffs[7];

                                    thePlayer.playerItems[6] = merchantItemOffer;
                                    break;
                                case ItemTypes.Necklace:
                                    thePlayer.playerMaxHealth -= thePlayer.playerItems[7].itemBuffs[0];
                                    thePlayer.playerHealth -= thePlayer.playerItems[7].itemBuffs[0];
                                    thePlayer.playerSpeed -= thePlayer.playerItems[7].itemBuffs[1];
                                    thePlayer.playerStrength -= thePlayer.playerItems[7].itemBuffs[2];
                                    thePlayer.playerIntelligence -= thePlayer.playerItems[7].itemBuffs[3];
                                    thePlayer.playerDefense -= thePlayer.playerItems[7].itemBuffs[4];
                                    thePlayer.attack -= thePlayer.playerItems[7].itemBuffs[5];
                                    thePlayer.weaponStrength -= thePlayer.playerItems[7].itemBuffs[6];
                                    thePlayer.playerTreasureFind -= thePlayer.playerItems[7].itemBuffs[7];

                                    thePlayer.playerItems[7] = merchantItemOffer;
                                    break;
                                case ItemTypes.Potion:
                                    thePlayer.numPotions++;
                                    break;
                            }
                        }

                        merchantChoseItem = false;
                        currentGameState = GameState.GameRunning;
                    }
                    if (kbs.IsKeyDown(Keys.N) && prevKbs.IsKeyUp(Keys.N))
                    {
                        merchantChoseItem = false;
                        currentGameState = GameState.GameRunning;
                    }
                    break;
                case GameState.GameRunning:
                    if (thePlayer.isFighting)
                    {
                        System.Threading.Thread.SpinWait(100000000);
                    }

                    thePlayer.Update(kbs, ref levelInTiles, enemyList, dungeonLevel, ref currentGameState, ref ftm, gameTime, this, treasure, loot, combat, levelSound);

                    foreach (Enemy e in enemyList)
                    {
                        e.Update(ref thePlayer);
                    }

                    ftm.Update(gameTime, this);

                    foreach (Tile t in levelInTiles)
                    {
                        //if (t.GetType() is LadderTile)

                        if (t.GetType().ToString() == "PankowGame13.LadderTile")
                        {
                            LadderTile tempTile = (LadderTile)t;
                            tempTile.Update(Content);
                        }
                        if (t.GetType().ToString() == "PankowGame13.TreasureTile")
                        {
                            TreasureTile tempTile = (TreasureTile)t;
                            tempTile.Update(Content);
                        }
                        if (t.GetType().ToString() == "PankowGame13.TrapTile")
                        {
                            TrapTile tempTile = (TrapTile)t;
                            tempTile.Update(Content);
                        }
                    }

                    if (thePlayer.playerHealth <= 0)
                    {
                        currentGameState = GameState.GameOver;
                    }

                    break;
                case GameState.GameOver:
                    foreach (Keys key in kbs.GetPressedKeys())
                    {
                        if (prevKbs.IsKeyUp(key))
                        {
                            if (key == Keys.Back)
                            {
                                if (tempPlayerName.Length > 0)
                                {
                                    tempPlayerName = tempPlayerName.Remove(tempPlayerName.Length - 1, 1);
                                }
                            }
                            else
                            {
                                if (tempPlayerName.Length < 3)
                                {
                                    tempPlayerName += key.ToString();
                                }
                            }
                        }
                    }
                    playerName = tempPlayerName;
                    if ((kbs.IsKeyDown(Keys.Enter) && prevKbs.IsKeyUp(Keys.Enter)) || (kbs.IsKeyDown(Keys.Space) && prevKbs.IsKeyUp(Keys.Space)))
                    {
                        playerName = playerName.Remove(3, playerName.Length - 3);
                        if (thePlayer.playerHealth > 0)
                        {
                            //exits dungeon successfully
                            highScore = thePlayer.playerTreasureAmount;

                            StreamWriter sw = new StreamWriter(highScorePath, true);
                            sw.WriteLine(playerName + "-" + highScore.ToString() + "-" + dungeonLevel);
                            sw.Close();
                            playerName = "AAA";
                        }

                        //read from high score file, and parse
                        highScores = ParseHighScores();

                        enemyList.Clear();
                        dungeonLevel = 1;
                        thePlayer.dungeonLevel = 1;

                        currentGameState = GameState.MainMenu;
                    }
                    break;
            }
            prevKbs = kbs;
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            switch (currentGameState)
            {
                case GameState.TitleScreen:
                    spriteBatch.Begin();

                    spriteBatch.Draw(titleScreen, new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), Color.White);

                    spriteBatch.End();
                    break;
                case GameState.MainMenu:
                    spriteBatch.Begin();

                    spriteBatch.Draw(mainMenu, new Rectangle(0,0,graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), Color.White);

                    //draw high scores
                    int xCoord = 75;
                    int yCoord = 450;
                    foreach (string score in highScores)
                    {
                        spriteBatch.DrawString(sf, score, new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                        yCoord += 40;
                    }

                    xCoord = 865;
                    yCoord = 425;
                    switch (currentMenuOption)
                    {
                        case MenuOptions.Adventurer:
                            spriteBatch.DrawString(sf, "Adventurer", new Vector2(xCoord, yCoord), Color.Yellow, 0.0f, Vector2.Zero, 2, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Hunter", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Mage", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Rogue", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Warrior", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            break;
                        case MenuOptions.Hunter:
                            spriteBatch.DrawString(sf, "Adventurer", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Hunter", new Vector2(xCoord, yCoord), Color.Yellow, 0.0f, Vector2.Zero, 2f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Mage", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Rogue", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Warrior", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            break;
                        case MenuOptions.Mage:
                            spriteBatch.DrawString(sf, "Adventurer", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Hunter", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Mage", new Vector2(xCoord, yCoord), Color.Yellow, 0.0f, Vector2.Zero, 2, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Rogue", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Warrior", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            break;
                        case MenuOptions.Rogue:
                            spriteBatch.DrawString(sf, "Adventurer", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Hunter", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Mage", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Rogue", new Vector2(xCoord, yCoord), Color.Yellow, 0.0f, Vector2.Zero, 2, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Warrior", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            break;
                        case MenuOptions.Warrior:
                            spriteBatch.DrawString(sf, "Adventurer", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Hunter", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Mage", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Rogue", new Vector2(xCoord, yCoord), Color.White, 0.0f, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
                            yCoord += 50;
                            spriteBatch.DrawString(sf, "Warrior", new Vector2(xCoord, yCoord), Color.Yellow, 0.0f, Vector2.Zero, 2, SpriteEffects.None, 0);
                            break;
                    }
                    
                    spriteBatch.End();
                    break;
                case GameState.GameRunning:
                    GraphicsDevice.Clear(Color.SaddleBrown);
            
                    spriteBatch.Begin();
                    spriteBatch.Draw(background, new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), Color.White);

                    foreach (Tile t in levelInTiles)
                    {
                        spriteBatch.Draw(t.tileTexture, t.tileRect, Color.White);
                    }

                    spriteBatch.Draw(thePlayer.playerSprite, thePlayer.playerPosition, Color.White);

                    foreach (Enemy e in enemyList)
                    {
                        if (e.isVisible)
                        {
                            spriteBatch.Draw(e.enemySprite, e.enemyRect, Color.White);
                        }
                    }

                    spriteBatch.DrawString(sf, "Class: " + thePlayer.playersClass, new Vector2(graphics.GraphicsDevice.Viewport.Width - 210, 10), Color.White);
                    spriteBatch.DrawString(sf, "Health: " + thePlayer.playerHealth, new Vector2(graphics.GraphicsDevice.Viewport.Width - 210, 30), Color.White);
                    spriteBatch.DrawString(sf, "Str: " + thePlayer.playerStrength, new Vector2(graphics.GraphicsDevice.Viewport.Width - 210, 50), Color.White);
                    spriteBatch.DrawString(sf, "Int: " + thePlayer.playerIntelligence, new Vector2(graphics.GraphicsDevice.Viewport.Width - 210, 70), Color.White);
                    spriteBatch.DrawString(sf, "Defense: " + thePlayer.playerDefense, new Vector2(graphics.GraphicsDevice.Viewport.Width - 210, 90), Color.White);
            
                    spriteBatch.DrawString(sf, "Speed: " + thePlayer.playerSpeed, new Vector2(graphics.GraphicsDevice.Viewport.Width - 210, 110), Color.White);
                    spriteBatch.DrawString(sf, "Weapon Str: " + thePlayer.weaponStrength, new Vector2(graphics.GraphicsDevice.Viewport.Width - 210, 130), Color.White);

                    spriteBatch.DrawString(sf, "Treasure Find: " + thePlayer.playerTreasureFind, new Vector2(graphics.GraphicsDevice.Viewport.Width - 210, 150), Color.White);
                    spriteBatch.DrawString(sf, "Treasure: " + thePlayer.playerTreasureAmount, new Vector2(graphics.GraphicsDevice.Viewport.Width - 210, 170), Color.White);

                    int eText = 200;
                    int enemyNumber = 1;
                    foreach (Enemy e in enemyList)
                    {
                        spriteBatch.DrawString(sf, "Enemy " + enemyNumber + ":" + e.status, new Vector2(graphics.GraphicsDevice.Viewport.Width - 190, eText), Color.White);
                        eText += 20;
                        enemyNumber++;
                    }

                    //draw player inventory
                    int itemPos = 300;
                    foreach (Item i in thePlayer.playerItems)
                    {
                        spriteBatch.Draw(i.itemPicture, new Rectangle((int)graphics.GraphicsDevice.Viewport.Width - 250, itemPos, 25, 25), Color.White);
                        //itemPos += 25;
                        spriteBatch.DrawString(sf, i.itemName, new Vector2(graphics.GraphicsDevice.Viewport.Width - 220, itemPos), Color.White);
                        itemPos += 40;
                    }
                    //draw potions
                    spriteBatch.Draw(potion, new Rectangle((int)graphics.GraphicsDevice.Viewport.Width - 180, itemPos, 25, 25), Color.White);
                    spriteBatch.DrawString(sf, thePlayer.numPotions.ToString(), new Vector2(graphics.GraphicsDevice.Viewport.Width - 120, itemPos), Color.White);

                    spriteBatch.DrawString(sf, "Dungeon Level: " + dungeonLevel.ToString(), new Vector2(graphics.GraphicsDevice.Viewport.Width - 190, itemPos + 80), Color.White);


                    //instructions
                    int textureHeight = 50;
                    spriteBatch.Draw(wasdKeys, new Rectangle(0, graphics.GraphicsDevice.Viewport.Height - 50, 100, textureHeight), Color.White);
                    spriteBatch.DrawString(sf, "Movement", new Vector2(105, graphics.GraphicsDevice.Viewport.Height - 50), Color.White);
                    spriteBatch.Draw(spaceBar, new Rectangle(210, graphics.GraphicsDevice.Viewport.Height - 50, 200, textureHeight), Color.White);
                    spriteBatch.DrawString(sf, "Activate Tile", new Vector2(415, graphics.GraphicsDevice.Viewport.Height - 50), Color.White);
                    spriteBatch.Draw(qKey, new Rectangle(570, graphics.GraphicsDevice.Viewport.Height - 50, 50, textureHeight), Color.White);
                    spriteBatch.DrawString(sf, "Drink Potion", new Vector2(625, graphics.GraphicsDevice.Viewport.Height - 50), Color.White);

                    //levelname
                    spriteBatch.DrawString(sf, levelList[currentLevel-1].Substring(0, levelList[currentLevel-1].Length-4), new Vector2(5,5), Color.White);

                    spriteBatch.End();
                    break;
                case GameState.ChangeLevel:
                    spriteBatch.Begin();

                    spriteBatch.Draw(levelChange, new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), Color.White);
                    spriteBatch.DrawString(sf, "Entering Dungeon Level: " + (thePlayer.dungeonLevel +1), new Vector2(graphics.GraphicsDevice.Viewport.Width / 2 - 340, graphics.GraphicsDevice.Viewport.Height / 2 - 250), Color.White, 0.0f, Vector2.Zero, 3, SpriteEffects.None, 0);

                    spriteBatch.End();

                    timeMark = gameTime.TotalGameTime.Seconds;

                    break;
                case GameState.Merchant:
                    spriteBatch.Begin();

                    spriteBatch.Draw(merchant, new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), Color.White);
                    spriteBatch.DrawString(sf, "Merchant Offers: " + merchantItemOffer.itemName, new Vector2(304, 120), Color.White);
                    spriteBatch.DrawString(sf, "For " + merchantItemPrice.ToString() + " Treasure", new Vector2(304, 150), Color.White);
                    spriteBatch.DrawString(sf, "Press Y to accept, Press N to decline", new Vector2(304, 180), Color.White);

                    spriteBatch.Draw(merchantItemOffer.itemPicture, new Rectangle(580, 395, 100, 100), Color.White);

                    spriteBatch.End();
                    break;
                case GameState.GameOver:
                    if (thePlayer.playerHealth > 0)
                    {
                        //winner
                        spriteBatch.Begin();

                        spriteBatch.Draw(gameOverGood, new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), Color.White);
                        spriteBatch.DrawString(sf, playerName + ": " + thePlayer.playerTreasureAmount + " Treasure!", new Vector2(293,725), Color.Black, 0.0f, Vector2.Zero, 3, SpriteEffects.None, 0);

                        spriteBatch.End();
                    }
                    else
                    {
                        //dead
                        spriteBatch.Begin();
                        
                        spriteBatch.Draw(gameOverBad, new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), Color.White);
                        
                        spriteBatch.End();
                    }
                    break;
            }

            spriteBatch.Begin();
            ftm.Draw(spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }

    static class MyExtensions
    {
        public static void Shuffle<T>(this IList<T> list)
        {
            Random rng = new Random();
            int n = list.Count;
            while (n > 1)
            {
                n--;
                int k = rng.Next(n + 1);
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }
    }
}
